package com.zxy.leetcode._01100_01199._01110_01119;

/**
 * https://leetcode-cn.com/problems/print-in-order/
 *
 * 可以用wait(),notify()，或者Semaphore，或者CountDownLatch 进行实现
 *
 */
public class Test01114 {

    public static void main(String[] args) {
        Runnable printFirst = () -> System.out.println("first");
        Runnable printSecond = () -> System.out.println("second");
        Runnable printThird = () -> System.out.println("third");

        Foo foo = new Foo();

        new Thread(() -> {
            try {
                foo.third(printThird);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                foo.first(printFirst);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                foo.second(printSecond);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }
}

class Foo {
    private Object lock = new Object();
    private boolean firstFinish = false;
    private boolean secondFinish = false;

    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {

        synchronized (lock) {
            // printFirst.run() outputs "firstFinish". Do not change or remove this line.
            printFirst.run();
            firstFinish = true;
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {

        synchronized (lock) {
            while (!firstFinish) {
                lock.wait();
            }
            // printSecond.run() outputs "secondFinish". Do not change or remove this line.
            printSecond.run();
            secondFinish = true;
            lock.notify();
        }

    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized (lock) {
            while (!secondFinish) {
                lock.wait();
            }
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
        }
    }
}
